<?php
/***************************************************************
*  Copyright notice
*  (c) 2009, jianyuzhu@gmail.com
*  All rights reserved
*  This script is part of the PPEMI project.
***************************************************************/

class CoreCheckCode {
	//
	var $font_path = 'images/fonts/';
	var $font_list = array(
        'Antykwa'  => array('spacing' => -3, 'minSize' => 27, 'maxSize' => 40, 'font' => 'AntykwaBold.ttf'),
        'Candice'  => array('spacing' =>-1.5,'minSize' => 28, 'maxSize' => 31, 'font' => 'Candice.ttf'),
        'DingDong' => array('spacing' => -2, 'minSize' => 24, 'maxSize' => 30, 'font' => 'Ding-DongDaddyO.ttf'),
        'Duality'  => array('spacing' => -2, 'minSize' => 30, 'maxSize' => 38, 'font' => 'Duality.ttf'),
        'Heineken' => array('spacing' => -2, 'minSize' => 24, 'maxSize' => 34, 'font' => 'Heineken.ttf'),
        'Jura'     => array('spacing' => -2, 'minSize' => 28, 'maxSize' => 32, 'font' => 'Jura.ttf'),
        'StayPuft' => array('spacing' =>-1.5,'minSize' => 28, 'maxSize' => 32, 'font' => 'StayPuft.ttf'),
        'Times'    => array('spacing' => -2, 'minSize' => 28, 'maxSize' => 34, 'font' => 'TimesNewRomanBold.ttf'),
        'VeraSans' => array('spacing' => -1, 'minSize' => 20, 'maxSize' => 28, 'font' => 'VeraSansBold.ttf'),
        //'HANDGOTB' => array('spacing' => -1, 'minSize' => 20, 'maxSize' => 28, 'font' => 'HANDGOTB.TTF'),
    );
	var $font_name = 'Antykwa';
	
	//
	var $session_sname = 'checkcode';
	
	//
	var $text = '';
	var $length = 4;
	
    /** Min word length (for non-dictionary random text generation) */
    var $minWordLength = 5;

    /**
     * Max word length (for non-dictionary random text generation)
     * 
     * Used for dictionary words indicating the word-length
     * for font-size modification purposes
     */
    var $maxWordLength = 8;
	
	//
	var $width = 120;
	var $height = 40;
	
    /** Background color in RGB-array */
    var $backgroundColor = array(255, 255, 255);

    /** Foreground colors in RGB-array */
    var $colors = array(
        array(27,78,181), // blue
        array(22,163,35), // green
        array(214,36,7),  // red
    );

    /** Shadow color in RGB-array or null */
    var $shadowColor = null; //array(0, 0, 0);
	
    /** Wave configuracion in X and Y axes */
    var $Yperiod    = 12;
    var $Yamplitude = 14;
    var $Xperiod    = 11;
    var $Xamplitude = 5;

    /** letter rotation clockwise */
    var $maxRotation = 8;

    /**
     * Internal image size factor (for better image quality)
     * 1: low, 2: medium, 3: high
     */
    var $scale = 2;

    /** 
     * Blur effect for better image quality (but slower image processing).
     * Better image results with scale=3
     */
    var $blur = false;

    /** Debug? */
    var $debug = false;
    
    /** Image format: jpeg or png */
    var $imageFormat = 'jpeg';
	
    /** GD image */
    var $im;
	
	//constructor
	function CoreCheckCode() {
		
	}
	
	//methods
	//generate image
	//
	function image() {
        $text = $this->_generate_code();
		$this->_session_scode($text);
		
		//
        $this->_image_allocate();
		if( $this->font_name != '' && isset($this->font_list[$this->font_name]) ) {
			$fontcfg = $this->font_list[$this->font_name];
		} else {
        	$fontcfg  = $this->font_list[array_rand($this->font_list)];
		}
        $this->_image_text($text, $fontcfg);

        if ($this->blur && function_exists('imagefilter')) {
            imagefilter($this->im, IMG_FILTER_GAUSSIAN_BLUR);
        }
        $this->_image_reduce();
		
        $this->_image_write();
        $this->_image_cleanup();
	}
	
	//
    function _image_allocate() {
        // Cleanup
        if (!empty($this->im)) {
            imagedestroy($this->im);
        }

        $this->im = imagecreatetruecolor($this->width*$this->scale, $this->height*$this->scale);

        // Background color
        $this->GdBgColor = imagecolorallocate($this->im,
            $this->backgroundColor[0],
            $this->backgroundColor[1],
            $this->backgroundColor[2]
        );
        imagefilledrectangle($this->im, 0, 0, $this->width*$this->scale, $this->height*$this->scale, $this->GdBgColor);

        // Foreground color
        $color           = $this->colors[mt_rand(0, sizeof($this->colors)-1)];
        $this->GdFgColor = imagecolorallocate($this->im, $color[0], $color[1], $color[2]);

        // Shadow color
        if (!empty($this->shadowColor) && is_array($this->shadowColor) && sizeof($this->shadowColor) >= 3) {
            $this->GdShadowColor = imagecolorallocate($this->im,
                $this->shadowColor[0],
                $this->shadowColor[1],
                $this->shadowColor[2]
            );
        }
    }
	
	//
	function _image_text($text, $fontcfg = array()) {
		if (empty($fontcfg)) {
			// Select the font configuration
			$fontcfg  = $this->font_list[array_rand($this->font_list)];
		}
		
		// Full path of font file
		$fontfile = $this->font_path.$fontcfg['font'];
		
		/** Increase font-size for shortest words: 9% for each glyp missing */
		$lettersMissing = $this->maxWordLength-strlen($text);
		$fontSizefactor = 1+($lettersMissing*0.09);
		
		// Text generation (char by char)
		$x      = 20*$this->scale;
		$y      = round(($this->height*27/40)*$this->scale);
		$length = strlen($text);
		for ($i=0; $i<$length; $i++) {
			$degree   = rand($this->maxRotation*-1, $this->maxRotation);
			$fontsize = rand($fontcfg['minSize'], $fontcfg['maxSize'])*$this->scale*$fontSizefactor;
			$letter   = substr($text, $i, 1);
			
			if ($this->shadowColor) {
				$coords = imagettftext($this->im, $fontsize, $degree,
								$x+$this->scale, $y+$this->scale,
								$this->GdShadowColor, $fontfile, $letter);
			}
			$coords = imagettftext($this->im, $fontsize, $degree,
								$x, $y,
								$this->GdFgColor, $fontfile, $letter);
			$x += ($coords[2]-$x) + ($fontcfg['spacing']*$this->scale);
		}
	}
	
	function _image_reduce() {
		$imResampled = imagecreatetruecolor($this->width, $this->height);
		imagecopyresampled($imResampled, $this->im,
			0, 0, 0, 0,
			$this->width, $this->height,
			$this->width*$this->scale, $this->height*$this->scale
		);
		imagedestroy($this->im);
		$this->im = $imResampled;
	}
	
	function _image_write() {
		if ($this->imageFormat == 'png' && function_exists('imagepng')) {
			header("Content-type: image/png");
			imagepng($this->im);
		} else {
			header("Content-type: image/jpeg");
			imagejpeg($this->im, null, 80);
		}
	}
	
	function _image_cleanup() {
		imagedestroy($this->im);
	}
	
	//check code
	//
	function check($code = '') {
		return $this->_check_code($code);
	}
	
	function _check_code($code) {
		$session_scode = isset($_SESSION[$this->session_sname]) ? $_SESSION[$this->session_sname] : '';
		
		if( $code == $session_scode ) {
			return true;
		}
		
		return false;
	}
	
	function _session_scode($code) {
		$_SESSION[$this->session_sname] = $code;
	}
	
	//generate code
	//
	function _generate_code() {
		$code = strtoupper(util_create_random_value('4', 'chars'));
		
		return $code;
	}
}
//
?>